Day10 是要實作可以用 Shift 來多選框框的題目
const checkboxData: string[] = [
"This is an inbox layout.",
"Check one item",
"Hold down your Shift key",
"Check a lower item",
"Everything in between should also be set to checked",
"Try to do it without any libraries",
"Just regular JavaScript",
"Good Luck!",
"Don't forget to tweet your result!",
];
const [checkedItems, setCheckedItems] = useState<boolean[]>(
new Array(checkboxData.length).fill(false)
);
const lastCheckedRef = useRef<number | null>(null);
判斷是否按到 Shift 且之前有選中框框
將最後選中的和目前選到的中間所有項目,設定為相同的狀態
const handleCheck = (
event: ChangeEvent<HTMLInputElement>,
index: number
): void => {
const newCheckedItems = [...checkedItems];
newCheckedItems[index] = !newCheckedItems[index];
if (
event.nativeEvent instanceof MouseEvent &&
event.nativeEvent.getModifierState("Shift") &&
lastCheckedRef.current !== null
) {
const start = Math.min(index, lastCheckedRef.current);
const end = Math.max(index, lastCheckedRef.current);
for (let i = start; i <= end; i++) {
newCheckedItems[i] = newCheckedItems[index];
}
}
setCheckedItems(newCheckedItems);
lastCheckedRef.current = index;
};
<div className="min-h-screen bg-gradient-to-br from-yellow-300 via-yellow-400 to-orange-400 flex items-center justify-center">
<div className="max-w-md w-full bg-white rounded-lg shadow-xl overflow-hidden">
{checkboxData.map((item, index) => (
<div
key={index}
className="flex border-b border-gray-200 last:border-b-0"
>
<label className="px-5 flex flex-1 items-center cursor-pointer">
<input
type="checkbox"
checked={checkedItems[index]}
onChange={(event) => handleCheck(event, index)}
className="h-5 w-5 mr-5 text-yellow-400 rounded focus:ring-yellow-400 focus:ring-opacity-25 cursor-pointer"
/>
<span
className={`flex-1 py-5 px-5 text-xl font-light border-l border-blue-100 transition-colors duration-200 ${
checkedItems[index] ? "bg-gray-100 line-through" : ""
}`}
>
{item}
</span>
</label>
</div>
))}
</div>
</div>